package com.easylinkin.linkappapi.elasticsearch.entity;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.easylinkin.linkappapi.calculaterule.entity.CalculateConfigAttribute;
import com.easylinkin.linkappapi.calculaterule.mapper.CalculateConfigAttributeMapper;
import org.apache.http.HttpHost;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * /**
 *
 * @author xuguoqing
 * @version [V1.0, 2020年04月26日]
 * @Description: Els 的client 的实例工厂，有开启有关闭
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@Service
public class ElsClientBeanFactory {
    @Resource
    private CalculateConfigAttributeMapper calculateConfigAttributeMapper;

    /**
     * 工厂模板的静态属性
     */
    public static int CONNECT_TIMEOUT_MILLIS = 20000;
    public static int SOCKET_TIMEOUT_MILLIS = 40000;
    public static int CONNECTION_REQUEST_TIMEOUT_MILLIS = 5000;
    public static int MAX_CONN_PER_ROUTE = 10;
    public static int MAX_CONN_TOTAL = 30;
    private static HttpHost HTTP_HOST;


    private RestClientBuilder builder;
    private RestHighLevelClient restHighLevelClient;

    //私有的静态单例
    private static ElsClientBeanFactory elsClientBeanFactory = new ElsClientBeanFactory();

    private ElsClientBeanFactory() {
        System.out.println("construct");
    }

    //这里的方法的巧妙
    //工厂的单例模式中就一个单例，如何实现单例的个性化
    //通过方法对类的私有静态变量进行修改，从而也实现了一个实例，多种个性
    public static ElsClientBeanFactory build(HttpHost httpHost, Integer maxConnectNum, Integer maxConnectPerRoute) {
        HTTP_HOST = httpHost;
        MAX_CONN_TOTAL = maxConnectNum;
        MAX_CONN_PER_ROUTE = maxConnectPerRoute;
        System.out.println("build one" + HTTP_HOST + "/" + maxConnectPerRoute);
        return elsClientBeanFactory;
    }

/*    public static ElsClientBeanFactory build(HttpHost httpHost, Integer connectTimeOut, Integer socketTimeOut, Integer connectionRequestTime, Integer maxConnectNum, Integer maxConnectPerRoute) {
        HTTP_HOST = httpHost;
        CONNECT_TIMEOUT_MILLIS = connectTimeOut;
        SOCKET_TIMEOUT_MILLIS = socketTimeOut;
        CONNECTION_REQUEST_TIMEOUT_MILLIS = connectionRequestTime;
        MAX_CONN_TOTAL = maxConnectNum;
        MAX_CONN_PER_ROUTE = maxConnectPerRoute;
        System.out.println("build two");
        return elsClientBeanFactory;
    }*/

    // bean 工厂的开启就会执行
    public void init() {
        builder = RestClient.builder(HTTP_HOST);
//        setHttpClientConfigCallback();
        setConnectTimeOutConfig();
        setMutiConnectConfig();
        restHighLevelClient = new RestHighLevelClient(builder);
        System.out.println("rrestHighLevelClient bean");
    }

    private void setHttpClientConfigCallback() {
        builder.setHttpClientConfigCallback(httpClientBuilder -> {
            // 1分钟
            httpClientBuilder.setKeepAliveStrategy((response, context) -> 1000 * 60);
            return httpClientBuilder;
        });
    }

    // 配置连接时间延时
    public void setConnectTimeOutConfig() {
        builder.setRequestConfigCallback(requestConfigBuilder -> {
            requestConfigBuilder.setConnectTimeout(CONNECT_TIMEOUT_MILLIS);
            requestConfigBuilder.setSocketTimeout(SOCKET_TIMEOUT_MILLIS);
            requestConfigBuilder.setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT_MILLIS);
            return requestConfigBuilder;
        });
    }

    // 使用异步httpclient时设置并发连接数
    public void setMutiConnectConfig() {
        builder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {

            @Override
            public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
                httpClientBuilder.setMaxConnTotal(MAX_CONN_TOTAL);
                httpClientBuilder.setMaxConnPerRoute(MAX_CONN_PER_ROUTE);
                httpClientBuilder.setKeepAliveStrategy((response, context) -> 1000 * 60);
                return httpClientBuilder;
            }
        });
    }

    public RestHighLevelClient getRhlClient() {
        return restHighLevelClient;
    }

    // bean 工厂的关闭应该销毁我们的示例
    public void close() {
        if (restHighLevelClient != null) {
            try {
                restHighLevelClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("restHighLevelClient client");
    }


    public List<String> getUnitCodeList(String dataSourceId) {
        QueryWrapper qw = new QueryWrapper();
        qw.eq("analyze_data_source_id", dataSourceId);
        qw.select("device_unit_code");
        List<CalculateConfigAttribute> list = calculateConfigAttributeMapper.selectList(qw);
        return list.stream().map(CalculateConfigAttribute::getDeviceUnitCode).collect(Collectors.toList());
    }

}

